<script lang="ts" setup>
import {ref, reactive, h, onBeforeMount} from "vue";
import Edit from './edit.vue';
import DataTable from '@/components/data-table/index.vue';
import {service} from "@/utils";
import {ElSwitch, ElMessageBox, ElLoading} from 'element-plus'
import {getDictTrim} from "@/api/system";

const dataTableRef = ref<InstanceType<typeof DataTable>>();
const editRef = ref<InstanceType<typeof Edit>>();
const columns = ref([
    {
        prop: 'title', label: '应用名称', width: 250, fixed: 'left', search: true,
        render: (row: any) => {
            return h(ElTooltip, {
                placement: "right-start",
                content: `<div style="width: 400px">
                            <span style="line-height: 25px">Feign名称:&nbsp;&nbsp;&nbsp;&nbsp;${row.name}</span><br>
                            <span style="line-height: 25px">部署模式:&nbsp;&nbsp;&nbsp;&nbsp;${row.deploymentMode}</span><br>
                            <span style="line-height: 25px">出产日期:&nbsp;&nbsp;&nbsp;&nbsp;${row.produceTime}</span><br>
                            <span style="line-height: 25px">描述:&nbsp;&nbsp;&nbsp;&nbsp;${row.description}</span>
                          </div>`,
                rawContent: true
            }, {
                default: () => {
                    return h('span', {}, {default: () => row.title})
                }
            });
        }
    },
    {prop: 'name', label: 'Feign名称', width: 250},
    {prop: 'deploymentMode', label: '部署模式', width: 180, tag: true},
    {prop: 'produceTime', label: '出产日期', width: 180, align: 'center', visible: false},
    {prop: 'version', label: '版本号', width: 100, align: 'right', visible: false},
    {prop: 'description', label: '描述', width: 300, tooltip: true, visible: false},
    {prop: 'uri', label: '项目URI', minWidth: 250, tooltip: true},
    {
        prop: 'status', label: '状态', minWidth: 120, align: 'center', tag: true,
        options: [
            {label: '已停止', value: 1, type: 'info'},
            {label: '运行中', value: 2, type: 'success'}
        ]
    },
    {prop: 'primary', label: '主从', width: 120, align: 'center', slot: true},
    {prop: 'createTime', label: '创建时间', width: 180, visible: false},
    {
        type: 'action', width: 300, maxCollapseButtons: 3,
        render: [
            {label: 'Ping', icon: 'el-icon-connection', onClick: (row: any) => properties.handle.ping(row)},
            {auth: 'module:update', onClick: (row: any)=> properties.handle.form(row)},
            {auth: 'module:delete', onClick: (row: any)=> properties.handle.delete(row)},
            {auth: 'module:close', onClick: (row: any)=> properties.handle.stopCommand(row)},
            {auth: 'module:upgrade', onClick: (row: any)=> properties.handle.upgrade(row)},
            {auth: 'module:download:shell', onClick: (row: any)=> properties.handle.download(row)},
        ],
    }
])
const properties = reactive({
    enums: {},
    handle: {
        refresh: (data?: any) => {
            dataTableRef.value.refresh(data)
        },
        loadEnumsData: () => {
            getDictTrim('sys_module', 'deployment_mode').then(({data}) => {
                Object.keys(data).forEach((field: string) => {
                    properties.enums[field.toCamelCase()] = Array.from(data[field]).map((item: any) => {
                        item.effect = 'dark';
                        switch (item.key) {
                            case '0':item.type = 'primary';break
                            case '1':item.type = 'success';break
                            case '2':item.type = 'warning';break
                        }
                        return item;
                    });
                })
            })
        },
        form: (row?: any) => {
            editRef.value?.open({
                data: row,
                confirm: {
                    action: properties.handle.edit,
                    success: properties.handle.refresh
                }
            }, properties.enums)
        },
        edit: (form: any, operate: string) => {
            return service[operate === 'update'? 'put':'post']('/module', form);
        },
        delete: (row: any) => {
            service.confirm(`确定删除应用名称:${row.title}, 访问地址:${row.uri}`, {
                url: '/module',
                data: {name: row.name, id: row.id},
                success: properties.handle.refresh
            })
        },
        ping: (row: any) => {
            const loadingInstance = ElLoading.service({lock: true, text: '正在Ping...', background: 'rgba(0, 0, 0, 0.7)'})
            service.get('/module/ping', {id: row.id}).then(({data}) => {
                ElMessageBox({
                    title: 'Ping',
                    message: h('div', { style: 'white-space: pre-wrap' }, data),
                }).then(()=>{
                    properties.handle.refresh();
                })
            }).finally(loadingInstance.close)
        },
        check: () => {
            const loadingInstance = ElLoading.service({lock: true, text: '正在检测所有应用运行状态...', background: 'rgba(0, 0, 0, 0.7)'})
            service.get('/module/check').then(() => properties.handle.refresh()).finally(loadingInstance.close)
        },
        download: (row: {id: string}) => {
            service.download('/module/shell', {id: row.id})
        },
        stopCommand: (row: any) => {
            let msg = `确定关闭${row.title}(${row.uri})应用?`;
            if (row.operate === 'restart') msg = `确定重新启动${row.title}(${row.uri})应用，操作后该应用在一段时间内无法访问?`
            service.confirm(msg, {
                url: '/module/close',
                type: 'post',
                data: {id: row.id},
                success: ({code}) => {
                    if (code === 200) {
                        setTimeout(() => properties.handle.refresh(), 3000)
                    }
                },
            })
        },
        command: (row: any, operate: string) => {
            return {
                id: row.id,
                title: row.title,
                uri: row.uri,
                installPath: row.installPath,
                operate: operate
            };
        },
        change: (row: any) => {
            service.put('/module/changedPrimary', {id: row.id, name: row.name, url: row.url, primary: row.primary}).then(({code}) => {
                if (code !== 200) {
                    row.primary = !row.primary;
                } else {
                    properties.handle.refresh();
                }
            })
        },
        upgrade: (row: any) => {
            const loading = ElLoading.service({lock: true, text: '正在加载相关应用信息...', background: 'rgba(0, 0, 0, 0.7)'})
            let apps: any[];
            service.get('/module/name', {name: row.name, primary: false}).then(({code, data}) => {
                apps = code === 200?data:[]
                if (apps) {
                    let offline = apps.filter( (it: any) => it.status !== 2);
                    let online = apps.filter( (it: any) => it.status === 2);
                    let success = 0, fail = 0;
                    loading.setText(`正在压缩资源...`)
                    service.post('/module/upgrade', {appName: row.appName, uri: row.uri, step: 0}).then(({code}) => {
                        if (code === 200) {
                            loading.setText(`共计: ${data.length}个应用, 离线: ${offline.length}个, 已更新: ${success}/${online.length}个, 失败: ${fail}个`)
                            online.forEach(item => {
                                service.post('/module/upgrade', {appName: item.appName, uri: item.uri, step: 1}).then(({code}) => {
                                    if (code === 200) {
                                        success ++;
                                    } else {
                                        fail ++;
                                    }
                                    loading.setText(`共计: ${data.length}个应用, 离线: ${offline.length}个, 已更新: ${success}/${online.length}个, 失败: ${fail}个`)
                                    if (online.length === (success + fail)){
                                        setTimeout(() => loading.close(), 1500)
                                    }
                                })
                            })
                        } else {
                            loading.close();
                        }
                    })
                } else {
                    loading.setText('应用信息加载失败,请联系管理员')
                    setTimeout(() => loading.close(), 3000)
                }
            })
        }
    }
})
onBeforeMount(() => properties.handle.loadEnumsData())
</script>
<template>
    <main-page>
        <data-table ref="dataTableRef" api="/module" :columns="columns" :enums="properties.enums" pagination>
            <template #button>
                <el-button v-auth="'module:add'" @click="properties.handle.form()"></el-button>
                <el-button @click="properties.handle.check()">Ping全部应用</el-button>
            </template>
            <template #primary="{scope}">
                <el-switch v-model="scope.row.primary" active-text="主" inactive-text="从" inline-prompt
                           @change="properties.handle.change(scope.row)" :disabled="scope.row.status === 2"
                           style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"/>
            </template>
        </data-table>

        <edit ref="editRef"/>
    </main-page>
</template>
<style scoped>
.mod-module .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.mod-module ::v-deep(.el-card__header) {
    padding: 10px;
}

::v-deep(.is-disabled .el-input__wrapper) {
    background-color: transparent;
}

.module-input ::v-deep(.el-input__wrapper) {
    box-shadow: 0 0 0 0 var(--el-input-border-color, var(--el-border-color)) inset
}

.module-input ::v-deep(.el-input__wrapper.is-focus) {
    box-shadow: 0 0 0 1px var(--el-input-focus-border-color, var(--el-border-color)) inset
}

.mod-module .el-button:focus-visible {
     outline: 0 solid var(--el-button-outline-color);
     outline-offset: 1px;
}
</style>
